package org.kjtc.security;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.kjtc.dao.DaoSupport;
import org.kjtc.entity.Resources;
import org.kjtc.entity.RoleResources;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Service;

@Service("mySecurityMetadataSource")
public class MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource {

	@Resource(name = "daoSupport")
	private DaoSupport dao;

	// 返回所请求资源所需要的权限
	@Override
	public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
		String requestUrl = ((FilterInvocation) object).getRequestUrl();
		if (requestUrl.indexOf("?") > 0) {
			requestUrl = requestUrl.substring(0, requestUrl.indexOf("?"));
		}
		if (requestUrl.toLowerCase().indexOf("realtime") < 0) {
			System.out.println("requestUrl is " + requestUrl);
		}
		if (resourceMap == null) {
			loadResourceDefine();
		}

		Set<String> urlMatch = resourceMap.keySet();
		for (String url : urlMatch) {
			if(requestUrl.equals(url)){
				int length = resourceMap.get(url).size();
				if (length > 0) {
					return resourceMap.get(url);
				}
			}
		}
		Collection<ConfigAttribute> configAttributes = new HashSet<ConfigAttribute>();
		configAttributes.add(new SecurityConfig("NOROLE"));
		return configAttributes;
	}

	@Override
	public Collection<ConfigAttribute> getAllConfigAttributes() {
		if (resourceMap == null) {
			loadResourceDefine();
		}
		Set<ConfigAttribute> allAttributes = new HashSet<ConfigAttribute>();
		for (Map.Entry<String, Collection<ConfigAttribute>> entry : resourceMap.entrySet()) {
			allAttributes.addAll(entry.getValue());
		}
		return allAttributes;
	}

	@Override
	public boolean supports(Class<?> clazz) {
		return true;
//		return FilterInvocation.class.isAssignableFrom(clazz);
	}

	public static Map<String, Collection<ConfigAttribute>> resourceMap = null;

	@SuppressWarnings("unchecked")
	public void reloadResourceDefine() {
		try {
			resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
			List<Resources> resources = (List<Resources>)this.dao.findForList("T_Resources.getResourcesInfo", null);
			for (Resources resource : resources) {
				RoleResources roleResources = new RoleResources();
				roleResources.setResourcesID(resource.getResourcesID());
				List<RoleResources> roleResourceList = (List<RoleResources>)this.dao.findForList("T_RoleResources.getUrlOfRole", roleResources);
				Collection<ConfigAttribute> configAttributes = new HashSet<ConfigAttribute>();
				for (RoleResources roleResource : roleResourceList) {
					SecurityConfig securityConfig = new SecurityConfig(roleResource.getRoleID());
					configAttributes.add(securityConfig);
					securityConfig = null;
				}
				resourceMap.put(resource.getUrl(), configAttributes);
				configAttributes = null;
				roleResources = null;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	};

	@SuppressWarnings("unchecked")
	private void loadResourceDefine() {
		if (resourceMap == null) {
			try {
				resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
				List<Resources> resources = (List<Resources>)this.dao.findForList("T_Resources.getResourcesInfo", null);
				for (Resources resource : resources) {
					RoleResources roleResources = new RoleResources();
					roleResources.setResourcesID(resource.getResourcesID());
					List<RoleResources> roleResourceList = (List<RoleResources>)this.dao.findForList("T_RoleResources.getUrlOfRole", roleResources);
					Collection<ConfigAttribute> configAttributes = new HashSet<ConfigAttribute>();
					for (RoleResources roleResource : roleResourceList) {
						SecurityConfig securityConfig = new SecurityConfig(roleResource.getRoleID());
						configAttributes.add(securityConfig);
						securityConfig = null;
					}
					resourceMap.put(resource.getUrl(), configAttributes);
					configAttributes = null;
					roleResources = null;
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}
